package com.swc.wrapper;

import com.google.common.base.Splitter;

import com.swc.constant.HeaderConstant;
import com.swc.factory.EncryptModeFactory;
import com.swc.property.SecretKeyProperty;
import com.swc.secret.AbstractSecret;
import com.swc.sign.Sha256Sign;
import com.swc.util.RsaUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

/**
 * 重新包装http, 解密请求的内容
 * @author HU
 * @date 2020/9/17 14:17
 */
public class DecryptReqParamWrapper extends HttpServletRequestWrapper {

	private Logger logger = LoggerFactory.getLogger(DecryptReqParamWrapper.class);

	private SecretKeyProperty rsaKeyProperty;
	private String queryString;
	private HttpServletRequest request;
	private AbstractSecret abstractSecret;
	private String secretKey;

	/**
	 * 初始化参数Map集合
	 */
	private final Map<String, String[]> paramsMap = new HashMap<>();

	/**
	 * 构造方法
	 *
	 * @param request
	 */
	public DecryptReqParamWrapper(HttpServletRequest request, SecretKeyProperty rsaKeyProperty) {
		super(request);
		this.rsaKeyProperty = rsaKeyProperty;
		this.request = request;
		abstractSecret = new EncryptModeFactory().getEncryptMode(request.getHeader(HeaderConstant.HEADER_ENCRYPT_MODE));
		secretKey = RsaUtil.decrypt(request.getHeader(HeaderConstant.HEADER_SECRET_KEY), rsaKeyProperty.getRsaPrivateKey());
	}

	/**
	 * 重写getParameter，代表参数从当前类中的map获取
	 *
	 * @param name 参数名称
	 * @return String
	 */
	@Override
	public String getParameter(String name) {
		String[] values = this.paramsMap.get(name);
		if (values == null || values.length == 0) {
			return null;
		}
		return values[0];
	}

	/**
	 * 重写getParameterValues，代表参数从当前类中的map获取
	 *
	 * @param name 参数名称
	 * @return String[]
	 */
	@Override
	public String[] getParameterValues(String name) {
		return this.paramsMap.get(name);
	}

	/**
	 * 重写getParameterMap
	 *
	 * @return Map<String, String[]>
	 */
	@Override
	public Map<String, String[]> getParameterMap() {
		try {
			buildParameterMap();
		} catch (Exception e) {
			logger.warn("【网关层返回的数据处理】对请求的数据解密失败", e);
			throw new RuntimeException("网关层处理数据失败");
		}
		return paramsMap;
	}

	private void buildParameterMap() throws Exception {
		Map<String, String[]> parameterMap = this.getRequest().getParameterMap();
		if (parameterMap == null || parameterMap.isEmpty()) {
			return;
		}
		if (Objects.equals(HeaderConstant.HEADER_URL_PARAM_DECRYPT_YES, request.getHeader(HeaderConstant.HEADER_URL_PARAM_DECRYPT))) {
			decryptParameterMap();
			return;
		}
		for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
			String[] val = entry.getValue();
			this.paramsMap.put(entry.getKey(), new String[]{abstractSecret.decrypt(val[0], rsaKeyProperty.getRsaPrivateKey(), secretKey)});
		}
	}

	private void decryptParameterMap() throws Exception {
		String encryptQueryString = request.getQueryString();
		if (StringUtils.isBlank(encryptQueryString)) {
			return;
		}

		String val = getQueryStringParam(encryptQueryString, "request");
		if (StringUtils.isEmpty(val)) {
			return;
		}
		TreeMap<String, String> treeMap = new TreeMap<>();
		treeMap.put("request", val);
		Sha256Sign sha256Sign = new Sha256Sign(request);
		sha256Sign.dealRequestHeader(treeMap);
		if (!sha256Sign.verifySign(treeMap, secretKey).equals(request.getHeader(HeaderConstant.HEADER_SIGN_KEY))) {
			throw new RuntimeException("验签失败，请检查");
		}
		String paramValue = abstractSecret.decrypt(val, rsaKeyProperty.getRsaPrivateKey(), secretKey);
		queryString = paramValue;
		String[] params = paramValue.split("&");
		for (int i = 0; i < params.length; i++) {
			int splitIndex = params[i].indexOf("=");
			if (splitIndex == -1) {
				continue;
			}
			String key = params[i].substring(0, splitIndex);
			if (splitIndex < params[i].length()) {
				String value = params[i].substring(splitIndex + 1);
				this.paramsMap.put(key, new String[]{value});
			}
		}
	}

	@Override
	public String getQueryString() {
		return queryString;
	}

	public static String getQueryStringParam(String params, String name) {
		String[] paramArray = params.split("&");
		Map<String, String> paramsMap = new HashMap<>();
		for (String param : paramArray) {
			int firstEqualIdx = param.indexOf("=");
			paramsMap.put(param.substring(0, firstEqualIdx), param.substring(firstEqualIdx + 1));
		}

		String val = paramsMap.get(name);
		if (StringUtils.isNotBlank(val)) {
			val = URLDecoder.decode(val);
		}
		return val;
	}


}